/**
 * @class This static class adds more methods to prototype's extended Element class (just use $() to invoke these methods)
 * @author erik 7/25/2008
 */

Company.UI.Element = {
	/**
	 * Returns true if the display of the element is not "none"
	 * @param {String} element The id of the element or a prototype augmented element object
	 */
	isDisplayed: function(element) {
		return $(element).getStyle("display") != 'none';
	},
	
	getBoxModel: function(element) {
		if (!Company.UI.Element.boxModel) {
			var html = 	'<div id="boxModelTest" style="display: none; width: 100px; height: 100px; border: solid 5px;"></div>';
			new Insertion.Bottom($$("BODY")[0], html);
			var testElement = $("boxModelTest");
			if (testElement.getWidth() == 100) {
				Company.UI.Element.boxModel = "Standard";
			} else {
				Company.UI.Element.boxModel = "IE";
			}
			testElement.remove();
		}
		
		return Company.UI.Element.boxModel;
	},
	
		
	/**
	 * Resizes the element to the given size
	 * @param {String} element The id of the element or a prototype augmented element object
	 * @param {Number} width The desired width or null for no change
	 * @param {Number} height The desired height or null for no change
	 */
	sizeTo: function(element, width, height) {
		if (width < 0) width = 0;
		if (height < 0) height = 0;
			
		if (element.style.pixelWidth) {
			if (width !== null) element.style.pixelWidth = width;
			if (height !== null) element.style.pixelHeight = height;
		} else {
			if (width !== null) element.style.width = width + "px";
			if (height !== null) element.style.height = height + "px";
		}
	},
		
		
	/**
	 * Moves the element to the given coordinates
	 * @param {String} element The id of the element or a prototype augmented element object
	 * @param {Number} left The desired horizonal position or null for no change
	 * @param {Number} top The desired vertical position or null for no change
	 */
	moveTo: function(element, left, top) {
		element = $(element);
		if (element.style.pixelLeft) {
			if (left !== null) element.style.pixelLeft = left;
			if (top !== null) element.style.pixelTop = top;
		} else {
			if (left !== null) element.style.left = left + "px";
			if (top !== null) element.style.top = top + "px";
		}	
	},
		
		
	/**
	 * Moves the element by the given amounts
	 * @param {String} element The id of the element or a prototype augmented element object
	 * @param {Number} left The desired horizonal move
	 * @param {Number} top The desired vertical move
	 */
	moveBy: function(element, h, v) {
		element = $(element);
		if (element.style.pixelLeft) {
			element.style.pixelLeft = element.offsetLeft + h;
			element.style.pixelTop = element.offsetTop + v;
		} else {
			element.style.left = (element.offsetLeft + h) + "px";
			element.style.top = (element.offsetTop + v) + "px";
		}
	},
	
	/**
	 * Removes all descendants of an element
	 * @param {String} element The id of the element or a prototype augmented element object
	 */
	setToEmpty: function(element) {
		element = $(element);
		element.innerHTML = "";
	},
	
	/**
	* Returns the width and height of the element outside of borders
	* @param {String} element The id of the element or a prototype augmented element object
	* @author Erik 10/4/2008
	*/
	getBorderDimensions: function(element) {
		var boxModel = element.getBoxModel();
		element = $(element);

		var borderWidth = element.getWidth();
		borderWidth += element.getStylePixels("border-left-width") + element.getStylePixels("border-right-width");

		var borderHeight = element.getHeight();
		borderHeight += element.getStylePixels("border-top-width") + element.getStylePixels("border-bottom-width");

		return { width: borderWidth, height: borderHeight };
	},
	
	
	/**
	* Returns the inner width and height of the element (inside of borders and padding)
	* @param {String} element The id of the element or a prototype augmented element object
	* @author Erik 10/4/2008
	*/
	getInnerDimensions: function(element) {
		var boxModel = element.getBoxModel();
		element = $(element);
		var outerDimensions = element.getDimensions();

		var innerWidth = outerDimensions.width;
		innerWidth += element.getStylePixels("padding-left") + element.getStylePixels("padding-right");
		innerWidth -= element.getStylePixels("border-left-width") + element.getStylePixels("border-right-width");

		var innerHeight = outerDimensions.height;
		innerHeight += element.getStylePixels("padding-top") + element.getStylePixels("padding-bottom");
		innerHeight -= element.getStylePixels("border-top-width") + element.getStylePixels("border-bottom-width");

		return {width: innerWidth, height: innerHeight};
	},
	
	
	/**
	* Sets the width, height, left and right of an element to the same as another element
	* @param {String} element The id of the element to reposition or a prototype augmented element object
	* @param {String} source The element to use as the source
	* @author Erik 10/12/2008
	*/
	cloneInnerPosition: function(element, source) {
		var boxModel = element.getBoxModel();
		
		// find page position of source
		source = $(source);
		var position = source.viewportOffset();
		if (boxModel == "Standard") position.left += source.getStylePixels("padding-left");
		if (boxModel == "Standard") position.top += source.getStylePixels("padding-top");
		position.left += source.getStylePixels("border-left-width");
		position.top += source.getStylePixels("border-top-width");
		
		var dimensions = source.getInnerDimensions();
		dimensions.width -= (element.getStylePixels("margin-left") + element.getStylePixels("margin-right"));
		dimensions.width -= source.getStylePixels("padding-left") + source.getStylePixels("padding-right");
		if (boxModel == "Standard") dimensions.width -= element.getStylePixels("padding-left") + element.getStylePixels("padding-right");
		if (boxModel == "Standard") dimensions.width -= element.getStylePixels("border-right-width") + element.getStylePixels("border-left-width");
		dimensions.height -= element.getStylePixels("margin-top") + element.getStylePixels("margin-bottom");
		dimensions.height -= source.getStylePixels("padding-top") + source.getStylePixels("padding-bottom");
		if (boxModel == "Standard") dimensions.height -= element.getStylePixels("padding-top") + element.getStylePixels("padding-bottom");
		if (boxModel == "Standard") dimensions.height -= element.getStylePixels("border-top-width") + element.getStylePixels("border-bottom-width");

		// find coordinate system to use
		element = $(element);
		var delta = {left: 0, top: 0};
		var parent = null;
		// delta [0,0] will do fine with position: fixed elements,
		// position:absolute needs offsetParent deltas
		if (Element.getStyle(element, 'position') == 'absolute') {
		  parent = element.getOffsetParent();
		  delta = parent.viewportOffset();
		}

		// correct by body offsets (fixes Safari)
		if (parent == document.body) {
		  delta.left -= document.body.offsetLeft;
		  delta.top -= document.body.offsetTop;
		}

		if (boxModel == "Standard") delta.left += source.getStylePixels("padding-left");
		if (boxModel == "Standard") delta.top += source.getStylePixels("padding-top");

		// set position
		element.moveTo(position.left - delta.left, position.top - delta.top);
		element.sizeTo(dimensions.width, dimensions.height);
		return element;
	},
	
	getParentBackground: function(element) {
		var background = 'transparent';
		var parent = element;
		while (background == 'transparent') {
			parent = $(parent.parentNode);
			background = parent.getStyle("background-color");
			if (parent === $(document.body)) break;
		}
		return background;
	},
	
	/**
	 * Returns pixel size of a style property like padding-left, border-top-width, etc. as an integer
	 * @param {String} element The id of the element to reposition or a prototype augmented element object
	 * @param {String} property The name of the style property
	 */
	getStylePixels: function(element, property) {
		var size = parseInt(element.getStyle(property));
		if (isNaN(size)) size = 0;
		return size;
	}

}

Element.addMethods(Company.UI.Element);